﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Microsoft.Practices.Unity;
using System.Configuration;
using Microsoft.Practices.Unity.Configuration;
using Prologis.Connect;
using Prologis.Logging;
using System.Reflection;
using Prologis.Connect.Tcp;

namespace Prologis.SchemaCommunicator
{
    public static class UnityResolver
    {
        static Logger log = new Logger(MethodBase.GetCurrentMethod().DeclaringType.Namespace);


        /// <summary>
        /// 
        /// </summary>
        /// <param name="configPathCommunicator"></param>
        /// <returns></returns>
        public static Communicator BuildCommunicator(string configPathCommunicator)
        {
            log.Info("in  BuildCommunicator(string configPathCommunicator)");

            IUnityContainer container = new UnityContainer();
            UnityConfigurationSection section = GetUnityConfigurationSection(configPathCommunicator);

            section.Containers.Default.Configure(container);

            log.Info("Unity Builder success: BuildCommunicator = " + configPathCommunicator);

            return BuildCommunicator(container);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="configPathCommunicator"></param>
        /// <param name="configPathCommons"></param>
        /// <returns></returns>
        public static Communicator BuildCommunicator(string configPathCommunicator, string configPathCommons)
        {
            IUnityContainer parentContainer = new UnityContainer();
            UnityConfigurationSection sectionCommons = GetUnityConfigurationSection(configPathCommons);
            sectionCommons.Containers.Default.Configure(parentContainer);

            log.Info("Unity Builder success: BuildCommunicator = " + configPathCommunicator + " , " + configPathCommons);

            return BuildCommunicator(configPathCommunicator, parentContainer);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="configPath"></param>
        /// <param name="parentContainer"></param>
        /// <returns></returns>
        public static Communicator BuildCommunicator(string configPath, IUnityContainer parentContainer)
        {
            IUnityContainer container = parentContainer.CreateChildContainer();
            UnityConfigurationSection section = GetUnityConfigurationSection(configPath);
            section.Containers.Default.Configure(container);

            log.Info("Unity Builder success: BuildCommunicator = " + configPath + " , " + parentContainer);

            return BuildCommunicator(container);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public static Communicator BuildCommunicator(IUnityContainer container)
        {
            var send = container.Resolve<SchemaControllerSend>("send");
            var comsend = container.Resolve<AsyncClientSocket>("sendSocket");
            var arbiter = container.Resolve<DualComArbiter>();
            var context = container.Resolve<CommunicatorContext>();
            Communicator cm = container.Resolve<Communicator>();

            BuildUpSchemaRegistry(container, cm);
            BuildUpBehaviorExtensions(container, cm);

            log.Info("Unity Builder success: BuildCommunicator = " + container);

            return cm;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="configPath"></param>
        /// <returns></returns>
        public static UnityConfigurationSection GetUnityConfigurationSection(string configPath)
        {
            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            map.ExeConfigFilename = configPath;

            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)config.GetSection("unity");

            log.Info("Unity Builder success: GetUnityConfigurationSection = " + configPath);

            return section;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <param name="cm"></param>
        public static void BuildUpSchemaRegistry(IUnityContainer container, Communicator cm)
        {
            foreach (Schema sd in cm.Context.SchemaRegistry)
            {
                sd.SchemaControllerSend = container.Resolve<ISchemaController>(sd.SchemaControllerSendName);
                sd.SchemaControllerReceive = container.Resolve<ISchemaController>(sd.SchemaControllerReceiveName);
                sd.Encoding = cm.Encoding;

                log.Info("Unity Builder success: BuildUpSchemaRegistry = " + sd);
            }
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <param name="cm"></param>
        public static void BuildUpBehaviorExtensions(IUnityContainer container, Communicator cm)
        {
            string names = cm.BehaviorExtensionNames;

            if (false == String.IsNullOrEmpty(names))
            {
                string[] namesArray = names.Split(',');
                //string[] namesArray = names.Replace(" ", "").Split(new char[]{',', ';'}, StringSplitOptions.RemoveEmptyEntries);
                foreach (string name in namesArray)
                {
                    ICommunicatorBehaviorExtension extension = container.Resolve<ICommunicatorBehaviorExtension>(name);

                    cm.BehaviorExtensions.Add(extension);

                    log.Info("Unity Builder success: BuildUpBehaviorExtensions = " + name);
                }
            }
        }

    }
    
}
